package edu.harding.redzone;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class OffenseModeView extends SurfaceView implements
		SurfaceHolder.Callback
{
	private int BOUNDARY;

	private final String OFFENSE = "offense";

	private static final int DRAW = 1;
	private static final int MOVE = 2;
	private static final int ERASE = 3;
	private static final int CLEAR = 4;
	private static final int BLOCK = 5;

	private static boolean mIsEdit;
	private ViewThread mThread;
	private static Play mPlay;
	private static Paint mPaint;
	private Point mCenter = new Point();
	private int LINE_SCRIMMAGE;
	private int mPlayerWidth;
	private int mPlayerHeight;
	private static Bitmap mBitmap;

	private int mColor;

	private static int mWidth;

	private static int mHeight;

	private Player mSelectedPlayer;

	private ArrayList<Point> mTrack = new ArrayList<Point>();

	private Point mPoint;

	private Point mMax = new Point();

	private Point mMin = new Point();

	private int LIMIT = 20;

	private int mPlayerColor;

	public static boolean IsEdit()
	{
		return mIsEdit;
	}

	public static Paint Paint()
	{
		return mPaint;
	}

	public static Bitmap Bitmap()
	{
		return mBitmap;
	}

	public static int Width()
	{
		return mWidth;
	}

	public static int Height()
	{
		return mHeight;
	}

	public static void IsEdit(boolean value)
	{
		mIsEdit = value;
	}

	public OffenseModeView(Context context)
	{
		super(context);
		initializeThread();
		initialize();
	}

	public OffenseModeView(Context context, AttributeSet attr)
	{
		super(context, attr);
		initializeThread();
		initialize();
	}

	public OffenseModeView(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		initializeThread();
		initialize();
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height)
	{
		mWidth = width;
		mHeight = height;

		mCenter.x = width / 2;
		mCenter.y = height / 2;
		LINE_SCRIMMAGE = mCenter.y;
		BOUNDARY = width / 12;
	}

	public void surfaceCreated(SurfaceHolder holder)
	{
		if (!mThread.isAlive())
		{
			mThread = new ViewThread(this);
			mThread.setRunning(true);
			mThread.start();
		}
	}

	public void surfaceDestroyed(SurfaceHolder holder)
	{
		if (mThread.isAlive())
		{
			mThread.setRunning(false);
		}
	}

	private void initializeThread()
	{
		getHolder().addCallback(this);
		mThread = new ViewThread(this);

	}

	private int PlayerColor(String color)
	{
		if (color.equals("1"))
		{
			mColor = 1;
			mPlayerColor = R.drawable.black;
		} else if (color.equals("2"))
		{
			mColor = 2;
			mPlayerColor = R.drawable.blue;
		} else if (color.equals("3"))
		{
			mColor = 3;
			mPlayerColor = R.drawable.cyan;
		} else if (color.equals("4"))
		{
			mColor = 4;
			mPlayerColor = R.drawable.gray;
		} else if (color.equals("5"))
		{
			mColor = 5;
			mPlayerColor = R.drawable.green;
		} else if (color.equals("6"))
		{
			mColor = 6;
			mPlayerColor = R.drawable.red;
		} else if (color.equals("7"))
		{
			mColor = 7;
			mPlayerColor = R.drawable.yellow;
		}
		RouteColor();

		return mPlayerColor;
	}

	private int RouteColor()
	{
		switch (mColor)
		{
		case 1:
			return Color.BLACK;
		case 2:
			return Color.BLUE;
		case 3:
			return Color.CYAN;
		case 4:
			return Color.GRAY;
		case 5:
			return Color.GREEN;
		case 6:
			return Color.RED;
		case 7:
			return Color.YELLOW;
		}
		return (Integer) null;
	}

	private void initialize()
	{
		mBitmap = BitmapFactory.decodeResource(getResources(),
				PlayerColor(MainActivity.PlayerColor()));

		initializePaint();

		mPlayerWidth = mBitmap.getWidth() / 2;
		mPlayerHeight = mBitmap.getHeight() / 2;
	}

	private void initializePaint()
	{
		setFocusable(true);

		mPaint = new Paint();
		mPaint.setDither(true);
		mPaint.setColor(RouteColor());
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeJoin(Paint.Join.ROUND);
		mPaint.setStrokeCap(Paint.Cap.ROUND);
		mPaint.setStrokeWidth(5);
	}

	private void defaultPlay()
	{
		int count = 0;
		int width = 0;

		width = mCenter.x - (BOUNDARY * 2);

		for (int i = 0; i < 5; i++)
		{
			mPlay.Players().get(i).X(width + count);
			mPlay.Players().get(i).Y(mCenter.y);
			mPlay.Players().get(i).IsSelected(false);
			mPlay.Players().get(i).Type(OFFENSE);
			count += BOUNDARY;
		}

		count = 0;
		width = mCenter.x - BOUNDARY;
		for (int i = 5; i < 8; i++)
		{
			mPlay.Players().get(i).X(width + count);
			mPlay.Players().get(i).Y(mCenter.y + (BOUNDARY * 2));
			mPlay.Players().get(i).IsSelected(false);
			mPlay.Players().get(i).Type(OFFENSE);
			count += BOUNDARY;
		}

		mPlay.Players().get(8).X(mCenter.x);
		mPlay.Players().get(8).Y(mCenter.y + BOUNDARY);
		mPlay.Players().get(8).IsSelected(false);
		mPlay.Players().get(8).Type(OFFENSE);

		mPlay.Players().get(9).X(mCenter.x - (BOUNDARY * 5));
		mPlay.Players().get(9).Y(mCenter.y);
		mPlay.Players().get(9).IsSelected(false);
		mPlay.Players().get(9).Type(OFFENSE);

		mPlay.Players().get(10).X(mCenter.x + (BOUNDARY * 5));
		mPlay.Players().get(10).Y(mCenter.y);
		mPlay.Players().get(10).IsSelected(false);
		mPlay.Players().get(10).Type(OFFENSE);
	}

	public void doDraw(Canvas canvas)
	{
		if (IsEdit() == false || OffenseModeActivity.Mode() == CLEAR)
		{
			mPlay = new Play(OFFENSE, "new", getResources());
			defaultPlay();
			IsEdit(true);

			OffenseModeActivity.Mode(-1);
		}

		canvas.drawColor(Color.WHITE);
		synchronized (mPlay)
		{
			for (Player player : mPlay.Players())
				player.doDraw(canvas, mPaint, mBitmap);
		}
	}

	public static Play PlayToView()
	{
		return mPlay;
	}

	public static Play PlayToSave()
	{
		return mPlay;
	}

	public static void PlayToEdit(Play play)
	{
		mPlay = play;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		if (OffenseModeActivity.Mode() == DRAW)
		{
			drawRoute(event);
		} else if (OffenseModeActivity.Mode() == MOVE)
		{
			movePlayers(event);
		} else if (OffenseModeActivity.Mode() == ERASE)
		{
			eraseRoute(event);
		}

		return true;
	}

	private void eraseRoute(MotionEvent event)
	{
		if (event.getAction() == MotionEvent.ACTION_DOWN)
		{
			mSelectedPlayer = setPlayerToSelected((int) event.getX()
					- mPlayerWidth, (int) event.getY() - mPlayerHeight);

		} else if (event.getAction() == MotionEvent.ACTION_UP)
		{
			if (mSelectedPlayer != null)
			{
				mSelectedPlayer.PathRoute().Path().reset();
				mSelectedPlayer.ResetLine();
				mSelectedPlayer.IsSelected(false);
			}
		}
	}

	private void drawRoute(MotionEvent event)
	{
		if (event.getAction() == MotionEvent.ACTION_DOWN)
		{
			mSelectedPlayer = setPlayerToSelected((int) event.getX()
					- mPlayerWidth, (int) event.getY() - mPlayerHeight);

			if (mSelectedPlayer != null)
			{
				mSelectedPlayer.PathRoute().PathPoints().clear();
				mSelectedPlayer.PathRoute().Path().reset();
				mSelectedPlayer.PathRoute().Path()
						.moveTo(event.getX(), event.getY());
				mSelectedPlayer.PathRoute().Path()
						.lineTo(event.getX(), event.getY());
			}
		} else if (event.getAction() == MotionEvent.ACTION_MOVE)
		{
			if (mSelectedPlayer != null)
			{
				mSelectedPlayer.PathRoute().Path()
						.lineTo(event.getX(), event.getY());
				setPathTrack(event, mSelectedPlayer);
			}
		} else if (event.getAction() == MotionEvent.ACTION_UP)
		{
			if (mSelectedPlayer != null)
			{
				mSelectedPlayer.PathRoute().Path()
						.lineTo(event.getX(), event.getY());
				mSelectedPlayer.PathRoute().PathPoints(mTrack);

				if (OffenseModeActivity.Route() == BLOCK)
					mSelectedPlayer
							.Line((int) event.getX(), (int) event.getY());

				mSelectedPlayer.IsSelected(false);
			}
		}
	}

	private void setPathTrack(MotionEvent event, Player player)
	{
		mPoint = new Point();
		mPoint.x = (int) event.getX();
		mPoint.y = (int) event.getY();
		mTrack.add(mPoint);
	}

	private void movePlayers(MotionEvent event)
	{
		if (event.getAction() == MotionEvent.ACTION_DOWN)
		{
			mSelectedPlayer = setPlayerToSelected((int) event.getX()
					- mPlayerWidth, (int) event.getY() - mPlayerHeight);
		} else if (event.getAction() == MotionEvent.ACTION_MOVE)
		{
			if (mSelectedPlayer != null)
			{
				mSelectedPlayer.PathRoute().Path().reset();
				mSelectedPlayer.ResetLine();
				moveSelectedPlayer((int) event.getX() - mPlayerWidth,
						(int) event.getY() - mPlayerHeight);
			}
		} else if (event.getAction() == MotionEvent.ACTION_UP)
		{
			if (mSelectedPlayer != null)
				mSelectedPlayer.IsSelected(false);

		}
	}

	private void moveSelectedPlayer(int x, int y)
	{
		if (y < LINE_SCRIMMAGE)
			y = LINE_SCRIMMAGE;

		mSelectedPlayer.X(x);
		mSelectedPlayer.Y(y);
	}

	private Player setPlayerToSelected(int x, int y)
	{
		mMax.x = x + LIMIT;
		mMax.y = y + LIMIT;
		mMin.x = x - LIMIT;
		mMin.y = y - LIMIT;

		for (Player player : mPlay.Players())
		{
			if (player.X() <= mMax.x && player.X() >= mMin.x
					&& player.Y() <= mMax.y && player.Y() >= mMin.y)
			{
				player.IsSelected(true);
				return player;
			}
		}

		return null;
	}
}
